﻿
Imports System.IO
Imports std
Imports storoomc

#Const SMALL_SIZE = True
'#Const STRONG_WRITE = True

Public Module _amutest

    Private Class info
        Public reader As TextReader = Nothing
        Public writer As TextWriter = Nothing
        Public keys As vector(Of String) = Nothing

        Public Sub New(ByVal reader As TextReader, ByVal writer As TextWriter, ByVal keys As vector(Of String))
            Me.writer = writer
            Me.reader = reader
            Me.keys = keys
        End Sub
    End Class

    Private Sub returnValueHandler(ByVal rtn As Boolean, ByVal writer As TextWriter, _
                                   ByVal action As String, Optional ByVal key As String = Nothing)
        Dim msg As String = Nothing
        msg = action + " "
        If Not isemptystring(key) Then
            msg += "key " + key + " "
        End If
        If rtn Then
            writer.WriteLine(msg + "success.")
        Else
            writer.WriteLine(msg + "failed.")
        End If
    End Sub

    Private Function generateRandomData() As bytes
#If RETIRED Then
        On Error Resume Next
        'sometimes, memory limited? createGUID returns empty string, which is somehow impossible.
        Return encoding.utf8.GetBytes(createGUID(rnd(10, 1000, True)))
#End If
        Dim rtn As bytes = Nothing
        rtn = New bytes()
#If SMALL_SIZE Then
        rtn.size() = rnd(100, 1000, True)
#Else
        rtn.size() = rnd(100000, 1000000, True)
#End If
        Dim i As Int64
        For i = 0 To rtn.size() - 1 Step rnd(1, 100, True)
            rtn(i) = rndbyte()
        Next

        Return rtn
    End Function

    Private Function randomSelectKey(ByVal info As info) As String
        Return info.keys(rnd(0, info.keys.size(), True))
    End Function

    Private Sub read(ByVal i As Object)
        Dim info As info = Nothing
        info = convertor.cast(Of info)(i)

        Dim key As String = Nothing
        key = randomSelectKey(info)

        returnValueHandler(storoom.read(key, Nothing), info.writer, "read", key)
    End Sub

    Private Sub write(ByVal i As Object)
        Dim info As info = Nothing
        info = convertor.cast(Of info)(i)

        Dim key As String = Nothing
        key = createGUID()

        returnValueHandler(storoom.write(key, generateRandomData()), info.writer, "write", key)
        info.keys.push_back(key)
    End Sub

    Private Sub uniqueWrite(ByVal i As Object)
        Dim info As info = Nothing
        info = convertor.cast(Of info)(i)

        Dim key As String = Nothing
        key = createGUID()

        returnValueHandler(storoom.uniqueWrite(key, generateRandomData()), info.writer, "uniqueWrite", key)
        info.keys.push_back(key)
    End Sub

    Private Sub delete(ByVal i As Object)
        Dim info As info = Nothing
        info = convertor.cast(Of info)(i)

        Dim key As String = Nothing
        key = randomSelectKey(info)

        returnValueHandler(storoom.delete(key), info.writer, "delete", key)
        'do not delete it from keys
        '1. performance
        '2. give some possibility to delete / modify / seek / sizeof a non-existing key
    End Sub

    Private Sub seek(ByVal i As Object)
        Dim info As info = Nothing
        info = convertor.cast(Of info)(i)

        Dim key As String = Nothing
        key = randomSelectKey(info)

        returnValueHandler(storoom.seek(key), info.writer, "seek", key)
    End Sub

    Private Sub list(ByVal i As Object)
        Dim info As info = Nothing
        info = convertor.cast(Of info)(i)

        Dim l As vector(Of String) = Nothing
        returnValueHandler(storoom.list(l), info.writer, "list", Convert.ToString(l.size()))
    End Sub

    Private Sub modify(ByVal i As Object)
        Dim info As info = Nothing
        info = convertor.cast(Of info)(i)

        Dim key As String = Nothing
        key = randomSelectKey(info)

        returnValueHandler(storoom.modify(key, generateRandomData()), info.writer, "modify", key)
    End Sub

    Private Sub sizeof(ByVal i As Object)
        Dim info As info = Nothing
        info = convertor.cast(Of info)(i)

        Dim key As String = Nothing
        key = randomSelectKey(info)

        returnValueHandler(storoom.sizeof(key, Nothing), info.writer, "sizeof", key)
    End Sub

    Private Sub full(ByVal i As Object)
        Dim info As info = Nothing
        info = convertor.cast(Of info)(i)

        returnValueHandler(storoom.full(), info.writer, "full")
    End Sub

    Private Sub health(ByVal i As Object)
        Dim info As info = Nothing
        info = convertor.cast(Of info)(i)

        returnValueHandler(storoom.health(), info.writer, "health")
    End Sub

    Private Sub capacity(ByVal i As Object)
        Dim info As info = Nothing
        info = convertor.cast(Of info)(i)

        Dim cap As UInt64
        returnValueHandler(storoom.capacity(cap), info.writer, "capacity", Convert.ToString(cap))
    End Sub

    Private Sub valuesize(ByVal i As Object)
        Dim info As info = Nothing
        info = convertor.cast(Of info)(i)

        Dim valuesize As UInt64
        returnValueHandler(storoom.valuesize(valuesize), info.writer, "valuesize", Convert.ToString(valuesize))
    End Sub

    Private Sub keycount(ByVal i As Object)
        Dim info As info = Nothing
        info = convertor.cast(Of info)(i)

        Dim keycount As UInt64
        returnValueHandler(storoom.keycount(keycount), info.writer, "keycount", Convert.ToString(keycount))
    End Sub

    Private Sub retire(ByVal i As Object)
        Dim info As info = Nothing
        info = convertor.cast(Of info)(i)

        returnValueHandler(storoom.retire(), info.writer, "retire")
    End Sub

    'this is a simple amutest, do not verify whether the data has been written to storoom
    Public Sub amutest(ByVal args As map(Of String, vector(Of String)), ByVal host As String, ByVal port As Int32, _
                       ByVal reader As TextReader, ByVal writer As TextWriter, _
                       ByVal holdtime As Int64, ByVal livetime As Int64)
        raiseError("********** automatical storoom unittest **********", errorHandle.errorType.application)
        Dim testsize As Int64 = 10000
        Dim testsizeInput As Int64
        Dim testsizeStr As String = Nothing
        If argmgr.getfirstvalue(args, "testsize", testsizeStr) AndAlso _
            convertor.toint64(testsizeStr, testsizeInput) Then
            testsize = testsizeInput
        End If
        storoom.initial(host, port, storoomc.common.talkTime.client2room.retrytimes)
        storoom.holdTime = holdtime
        storoom.liveTime = livetime

#If STRONG_WRITE Then
        randomrun.invoke(testsize, _
                         New info(reader, writer, New vector(Of String)), _
                         New randomrun.info(0.1, AddressOf read), _
                         New randomrun.info(0.5, AddressOf write), _
                         New randomrun.info(0.25, AddressOf uniqueWrite), _
                         New randomrun.info(0.05, AddressOf modify), _
                         New randomrun.info(0.005, AddressOf full), _
                         New randomrun.info(0.005, AddressOf capacity), _
                         New randomrun.info(0.04, AddressOf valuesize), _
                         New randomrun.info(0.05, AddressOf keycount))
#Else
        randomrun.invoke(testsize, _
                         New info(reader, writer, New vector(Of String)), _
                         New randomrun.info(0.1, AddressOf read), _
                         New randomrun.info(0.1, AddressOf write), _
                         New randomrun.info(0.1, AddressOf uniqueWrite), _
                         New randomrun.info(0.05, AddressOf delete), _
                         New randomrun.info(0.1, AddressOf seek), _
                         New randomrun.info(0.001, AddressOf list), _
                         New randomrun.info(0.1, AddressOf modify), _
                         New randomrun.info(0.1, AddressOf sizeof), _
                         New randomrun.info(0.0489, AddressOf full), _
                         New randomrun.info(0.05, AddressOf health), _
                         New randomrun.info(0.05, AddressOf capacity), _
                         New randomrun.info(0.1, AddressOf valuesize), _
                         New randomrun.info(0.1, AddressOf keycount), _
                         New randomrun.info(0.0001, AddressOf retire))
#End If
        raiseError("********** finish automatical unittest ***********", errorHandle.errorType.application)
    End Sub

End Module
